/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package be.ugent.medirem.persistence.facade;

import be.ugent.medirem.persistence.entity.Account;
import be.ugent.medirem.persistence.entity.GeneralPractitioner;
import be.ugent.medirem.persistence.entity.Location;
import be.ugent.medirem.persistence.entity.Patient;
import be.ugent.medirem.persistence.entity.details.GpDetails;
import be.ugent.medirem.persistence.entity.details.LocationDetails;
import be.ugent.medirem.persistence.entity.details.PatientDetails;
import be.ugent.medirem.persistence.entity.values.GpValues;
import be.ugent.medirem.persistence.util.EntityDetailsToEntity;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.EJBException;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.EntityNotFoundException;
import javax.persistence.PersistenceContext;

/**
 *
 * @author Simon
 */
@Stateless
public class GpDaoBean implements GpDaoLocal {

    @PersistenceContext
    private EntityManager em;

    public Long create(GpValues gpD, String password) throws IllegalArgumentException {
        if (password == null) {
            throw new IllegalArgumentException("Password can't be null.");
        }
        if (gpD.getUsername() == null) {
            throw new IllegalArgumentException("Username can't be null.");
        }
        try {
            GeneralPractitioner gp = EntityDetailsToEntity.detailsToGP(gpD, password);

            em.persist(gp);
            return gp.getId();
        } catch (Exception e) {
            throw new EJBException();
        }
    }

    public GpDetails getDetails(final Long id) throws EntityNotFoundException, IllegalArgumentException {
        try {
            GeneralPractitioner gp = em.find(GeneralPractitioner.class, id);
            if (gp == null) {
                throw new EntityNotFoundException(this.toString() + " Could not find gp with id " + id);
            }
            return EntityDetailsToEntity.gPToDetails(gp);
        } catch (Exception e) {
            throw new EJBException(e);
        }
    }

    public void update(GpValues gp) throws EntityNotFoundException, IllegalArgumentException {
        if (gp.getId() == null) {
            throw new IllegalArgumentException("Id can't be null.");
        }
        try {
            GeneralPractitioner g = em.find(GeneralPractitioner.class, gp.getId());
            if (g == null) {
                throw new EntityNotFoundException(this.toString() + " Could not find gp with id " + gp.getId());
            }

            if(gp.getFirstname() != null) {
                g.setFirstname(gp.getFirstname());
            }
            if(gp.getSurname() != null) {
                gp.setSurname(gp.getSurname());
            }
            if(gp.getUsername() != null) {
                gp.setUsername(gp.getUsername());
            }

            em.merge(g);
        } catch (Exception e) {
            throw new EJBException();
        }
    }

    public void update(Long gpId, Long locationId) throws EntityNotFoundException, IllegalArgumentException {
        GeneralPractitioner g = null;

        if (gpId == null) {
            throw new IllegalArgumentException("GP id is null");
        }
        if (locationId == null) {
            throw new IllegalArgumentException("Location id is null");
        }
        try {
            g = em.find(GeneralPractitioner.class, gpId);

            if (g == null) {
                throw new EntityNotFoundException();
            } else {
                Location l = em.find(Location.class, locationId);

                g.setLocation(l);

                em.merge(g);
            }
        } catch (Exception ex) {
            throw new EJBException(ex);
        }
    }

    public void updatePassword(Long id, String old, String password) throws EntityNotFoundException, IllegalArgumentException {
        if (password == null) {
            throw new IllegalArgumentException("Password can't be null.");
        }
        if (id == null) {
            throw new IllegalArgumentException("Id can't be null.");
        }

        try {
            GeneralPractitioner gp = em.find(GeneralPractitioner.class, id);

            if (gp == null) {
                throw new EntityNotFoundException();
            } else {
                if (Account.encryptPwd(old).equals(gp.getPassword())) {
                    gp.setPassword(password);
                    em.merge(gp);
                } else {
                    throw new IllegalArgumentException("Old password does not match");
                }
            }
        } catch (Exception ex) {
            throw new EJBException(ex);
        }
    }

    public LocationDetails getLocation(Long id) throws EntityNotFoundException {
        if (id == null) {
            throw new IllegalArgumentException("Id can't be null.");
        }
        try {
            GeneralPractitioner gp = em.find(GeneralPractitioner.class, id);
            if (gp == null) {
                throw new EntityNotFoundException(this.toString() + " Could not find gp with id " + id);
            }
            if(gp.getLocation() == null) {
                return null;
            }
            return EntityDetailsToEntity.locationToDetails(gp.getLocation());
        } catch (Exception e) {
            throw new EJBException();
        }
    }

    public List<PatientDetails> getPatients(final Long id) throws EntityNotFoundException, IllegalArgumentException {
        if (id == null) {
            throw new IllegalArgumentException("Id can't be null.");
        }
        List<PatientDetails> list = new ArrayList<PatientDetails>();

        try {
            GeneralPractitioner gp = em.find(GeneralPractitioner.class, id);
            if (gp == null) {
                throw new EntityNotFoundException(this.toString() + " Could not find gp with id " + id);
            }
            for (Patient p : gp.getPatients()) {
                list.add(EntityDetailsToEntity.patientToDetails(p));
            }
        } catch (Exception e) {
            throw new EJBException();
        }
        return list;
    }

    public void addPatient(Long id, Long patientId) throws EntityNotFoundException, IllegalArgumentException {
        if (id == null) {
            throw new IllegalArgumentException("Id can't be null.");
        }
        if (patientId == null) {
            throw new IllegalArgumentException("PatientId can't be null.");
        }

        try {
            GeneralPractitioner gp = em.find(GeneralPractitioner.class, id);
            Patient p = em.find(Patient.class, patientId);
            if (gp == null) {
                throw new EntityNotFoundException(this.toString() + " Could not find gp with id " + id);
            }
            if (p == null) {
                throw new EntityNotFoundException(this.toString() + " Could not find patient with id " + id);
            }
            gp.addPatient(p);
            em.merge(gp);
        } catch (Exception e) {
            throw new EJBException();
        }
    }

    public Long getGpId(String username) throws IllegalArgumentException {
        Long id = null;
        try {
            id = (Long) em.createNamedQuery("GeneralPractitioner.GetId").setParameter("username", username).getSingleResult();
        } catch (Exception ex) {
            throw new IllegalArgumentException("Username not found: " + username);
        }
        return id;
    }

    public boolean hasPatient(Long id, Long patient) {
        return em.createQuery("SELECT p FROM Patient p WHERE p.gp.id = :gp AND p.id = :id").setParameter("gp", id).setParameter("id", patient).getResultList().isEmpty();
    }
}
